<?php
//require_once('./Config/config.php');





/*
	### 检测指定内容是否匹配关键词表中的关键词
		参一：pdo对象
		参二：要匹配的内容数组
		return:	匹配成功返回true,未匹配返回false
		示例：
		if(Check_Keywords($pdo,array($_POST['info_title'],$_POST['info_content'],$_POST['info_contacts']))){
			$_POST['info_stat'] = 4;
		}
*/
function Check_Keywords($pdo,$keys_arr){
	global $config;
	$sql_keyword = "select content from {$config['table_prefix']}keyword";
	$res_keyword = $pdo->dql($sql_keyword,array());
	if(!$res_keyword){
		return false;
	}
	foreach($res_keyword as $v){
		$p = '/'.$v['content'].'/';

		foreach($keys_arr as $vv){
			if(preg_match($p,$vv)){
				return true;
			}
		}
	}
	return false;
}







/*
	### 获取倒查或正查的起始值
	    参一：pdo对象
		参二：要查询的表名
        参三：主键id的字段名
        参四：查询的范围 如：5000条
        返回：小于指定范围时为正查，反回0，大于指定范围时为倒查，返回大于0的倒查起始值
	    示例：
		    $Res = Get_NormalOrDescLimitId($Pdo,'bmxx8_info','info_id',100);
*/
function Get_NormalOrDescLimitId($Pdo, $TableName, $Feild, $DescCount) {
    $Sql = "select {$Feild} from {$TableName} order by {$Feild} desc limit {$DescCount},1";
    $Res = $Pdo->dql($Sql, array(), 1);
    if ($Res) {
        return $Res['info_id'];
    } else {
        return 0;
    }
}







//作废token值
function Token_Void($switch_type){
	if($switch_type != 'code'){
		$_SESSION[$switch_type] = sha1(microtime(1));	
	}
}












/*
	### 无限分页查询数据(不查询最大条数)
		参一：$pdo  PDO实例化的对象
		参二：$base_field	between 范围查询的字段名 如：'user_id'
		参三：$base_id 		between 起始值	如：11
		参四：$bet 		between 区间范围值  如：10000   
		参五：$table_name  要查询的表名  如：'bmxx8_user'
		参六：$limit  要查询多少条默认5条
		参七：$field  查询的字段默认为‘*’ 如：'user_id,user_name'; 
		参八：$where  where条件及对应值默认为空 如：array('user_ltime'=>154,'user_ctime'=>123);
		参九：$loop_num 设置do_while死循环查询的次数，默认为30次
		示例：
			$pdo = MyPdo::init();
			$base_field = 'user_id';
			$pnow = intval(@$_POST['pnow']) >= 0?intval(@$_POST['pnow']):1;
			$bet = 10000;
			$table_name = 'bmxx8_user';
			$limit = 5;
			$field = 'user_id,user_name,user_ctime,user_ltime,user_stat';
			$where = array('user_stat'=>5);
			$res = Fpage_NoCountQuery($pdo,$base_field,$pnow,$bet,$table_name,$limit,$field,$where);
			if($res == 'err'){
				exit('err');
			}
			echo json_encode($res);
*/
function Fpage_NoCountQuery($pdo,$base_field,$pnow,$bet,$table_name,$limit=5,$field='*',$where='',$loop_num=30){
	if($pnow == 1){
		$sql = "select max({$base_field}) as info_id from {$table_name}";
		$res = $pdo->dql($sql,array());

		if($res[0]['info_id']){
			$_SESSION['pnow1'] = $base_id = $res[0]['info_id'];
		}else{
			return 'err';	//没有数据
		}
	}else{
		$base_id = $_SESSION['pnow'.($pnow)];
	}

	$base_id2 = $base_id - $bet > 0 ? $base_id - $bet : 1;

	$loop_stat = true;
	$num = 0;
	do{
		//获取数据
		$where_arr = array();
		if($where){
			$where_str = '';
			foreach($where as $k=>$v){
				$where_str .= ' and '.$k.'=?';
				$where_arr[] = $v;
			}
		}else{
			$where_str = '';
		}


		$sql = "select {$field} from {$table_name} where {$base_field} between {$base_id2} and {$base_id} {$where_str} order by {$base_field} limit {$limit}";
		//echo $sql;exit;
		$res = $pdo->dql($sql,$where_arr);
		if($res){
			$_SESSION['pnow'.($pnow+1)] = $base_id = intval($res[count($res)-1]['user_id'])-1;
		}else{
			$base_id = $base_id2;
			$base_id2 = $base_id - $bet > 1 ? $base_id - $bet : 1;
		}
		//判断后续数据是否存在
		//$sql = "select {$base_field} as count from {$table_name} where {$base_field} < {$base_id2} limit 1";
		$sql = "select {$base_field} from {$table_name} where {$base_field} < {$base_id} limit 1";
		$res2 = $pdo->dql($sql,array());
		if($res || !$res2 || $num >= $loop_num){
			$loop_stat = false;
		}
		$num ++;
	}while($loop_stat);
	if($res){
		return $res;
	}else{
		return 'err';
	}
}










/*
	### 高性能无限分页数据查询(可用:推荐)
	参一：$pnow 	当前页
	参二：$table_name 	表名
	参三：$max_field 	主键字段名
	参四：$page_session_name 	记录页码的session缓存名
	参五：$where_field 		where条件的字段名
	参六：$field=false 		要查询哪些字段的名,默认为全查 *
	参七：$limit = 5   每页条数
	参八：$desc = false 	是否倒序，默认false为倒序,有值为正序

	示例：
		$pnow = $_POST['pnow'];
		$field = 'info_id,info_uid,info_service,info_stat,info_auto_issue,info_title,info_content,info_contacts,info_phone,info_issue_time,info_imgs';
		$max_field = 'info_id';		//查询max()最大值的主键字段名
		$table_name = 'bmxx8_info';	//表名
		$page_session_name = 'After_Get_Info_List_Page';	//设置当前要使用的分页session缓存名
		$where_field = 'info_stat';	//需要where 查询的字段名
		After_Get_Info_List($pnow,$table_name,$max_field,$page_session_name,$where_field,field,$limit,$desc);
		After_Get_Info_List($pnow,$table_name,$max_field,$page_session_name,$where_field,'',10,1);

	函数原理：
		当无where条件分页查询时，使用缓存当前页最后id值为下页起始查询基数的方式。先查询最大条数做为初始基数，每页倒查limit条后以最后一条id做为下页的基数，并保存到session 中。这样来实现高效的无限分页。
		当有where条件分页查询时，使用判断指定范围大小后是否正查或倒查的方式。
		区分是否有无where条件时，where字段($where_field)使用 all时是查询全部(无where条件).

	前台分页处理配合使用
		Fpage3(info.PageNo,function(pnow){
			sessionStorage.after_info_pnow = pnow;
			Get_User_info();
		});

	注：after_page_sess 为 session 中缓存每页码对应的id值的集合字段名
*/

/*function After_Get_Info_List($pnow,$table_name,$max_field,$page_session_name,$where_field,$field=false,$limit = 5,$desc = false){
	if($desc){
		$desc_stat='';
	}else{
		$desc_stat = 'desc';		
	}
	if(!$field){
		$field = '*';
	}
	//$pnow = $_POST['pnow'];
	$info_stat = @$_POST[$where_field];
	//$limit = 10;
	$pdo = MyPdo::init();
	if($info_stat == 'all' || !$where_field){
		if($desc){
			if(!@isset($_SESSION['after_page_sess'][$page_session_name])){
				$_SESSION['after_page_sess'][$page_session_name][$pnow] = 0;
			}
			$sql = "select {$field} from {$table_name} where $max_field > {$_SESSION['after_page_sess'][$page_session_name][$pnow]} order by {$max_field} limit {$limit}";
			$res = $pdo->dql($sql,array());
			if($res){
				$last_id = $res[count($res)-1][$max_field];
				$next_pnow = $pnow+1;
				$_SESSION['after_page_sess'][$page_session_name][$next_pnow] =$last_id;
				Merge_Or_Make_Cache($res,'',0,$pnow);
			}else{
				echo 'err3';
			}
		}else{
			$sql = "select max($max_field) as max_info_id from {$table_name}";
			$res = $pdo->dql($sql,array(),1);
			$count = $res['max_info_id'];
			if(!$count){
				exit('err1');
			}
			if(!@$_SESSION['after_page_sess'][$page_session_name]){
				$_SESSION['after_page_sess'][$page_session_name][$pnow] = $count;
			}else{
				if($_SESSION['after_page_sess'][$page_session_name][$pnow]=='end'){
					exit('err2');
				}
			}
			//当总条数少于每页基数时要使用<= ,不然前端会不显示

			$sql = "select {$field} from {$table_name} where $max_field <= {$_SESSION['after_page_sess'][$page_session_name][$pnow]} order by {$max_field} desc limit {$limit}";
			$res = $pdo->dql($sql,array());
			if($res){
				if($count <= $limit){
					$last_id = 'end';
				}else{
					$last_id = $res[count($res)-1][$max_field];
					if($_SESSION['after_page_sess'][$page_session_name][$pnow] == $last_id){
						exit('err5');
					}
				}
				$next_pnow = $pnow+1;
				$_SESSION['after_page_sess'][$page_session_name][$next_pnow] =$last_id;
				Merge_Or_Make_Cache($res,'',0,$pnow);
			}else{
				echo 'err3';
			}
		}
	}else{
		$where_info_stat = "and {$where_field} = {$info_stat}";
	    $desc_count = Get_NormalOrDescLimitId($pdo,$table_name,$max_field,10000);	//判断是否正倒查
	    $limit_start = ($pnow-1)*$limit;
		$sql = "select {$field} from {$table_name} where {$max_field} > {$desc_count} {$where_info_stat} order by {$max_field} {$desc_stat} limit {$limit_start},{$limit}";
		$res = $pdo->dql($sql,array());
		if($res){
			Merge_Or_Make_Cache($res,'',0,$pnow);
		}else{
			echo 'err4';
		}
	}
}
*/









/*
	### 无限分页函数集合一：按where条件获取信息数据
*/
function Get_Data_For_Fpage_Infinite_a($pdo,$table_name,$primary_key,$where,$order,$limit,$ignore,$max_page,$query_field){
	//如果where条件是数组,则拼接where条件字串，和pdo所需参数数组
	$where_str = '';
	$where_arr = array();
	if(is_array($where) && count($where) > 0){
		$where_str .= 'where ';
		foreach($where as $v){
			if($v[2] != 'like'){
				$where_str .= $v[0].$v[2].'? and ';
				$where_arr[] = $v[1];
			}else{
				$where_str .= $v[0]." like '%{$v[1]}%' and ";
			}
		}
		$where_str = trim($where_str,'and ');
	}
	$sql = "select {$query_field} from {$table_name} {$ignore} {$where_str} {$order} limit {$limit}";
/*	echo $sql;
	dump($where_arr,1);*/
	$res = $pdo->dql($sql,$where_arr);
	if($res){
		$ids_limit = $limit * $max_page;
		$sql2 = "select {$primary_key} from {$table_name} {$ignore} {$where_str} {$order} limit {$ids_limit}";
		//return $sql2;
		$res2 = $pdo->dql($sql2,$where_arr);

		$arr['data'] = $res;
		$arr['ids'] = $res2;
		return $arr;
	}else{
		return false;
	}

	
}


/*
	### 无限分页函数集合二：按where条件获取信息数据
		参一：pdo 对象
		参二: 当前页码
		参三: 缓存页码与对应数据id值的session缓存名,注要与where条件结合使用
		参四: 要查询的表名
		参五: 主键名
		参六: where条件数组,可为空 如：$where = array(array('info_uid',$uid,'='));
		参七: 是否正倒序查询,空为正查，有值为倒查
		参八: 每页要显示的条数
		参九: 是否忽略指定索引 如：'' 或 ignore index(uid) 
		参十: 当前页后续要查询的页数
		参十一：要缓存的路径，空为不缓存
		参十二：要查询的字段
		参十三：是直接显示数据还是return 数据，默认false 为显示数据
	### $_SESSION['after_page_sess'] 用来缓存所有记录页码与对应id值的缓存

	示例：
		$pnow = intval($_POST['pnow']);
		$uid = $_POST['uid'];
		$info_stat = $_POST['info_stat'];
		$where = array(array('info_uid',$uid,'=')); 
		if($info_stat != 'all'){
			array_push($where,array('info_stat',$info_stat,'='));
		}
		$ignore = 'ignore index(uid)';
		$max_page = 5;  对应前台Fpage4 中的参四 step
		$desc = 'desc';
		$arr_merge = array('pnow'=>$pnow,'max_page'=>$max_page);
		$cache_path = 'Cache/a';
		b($pnow,'After_Get_User_Issue_Info','bmxx8_info','info_id',$where,'desc',3,$ignore,$max_page,$cache_path,$query_field);

		配合前台分页码
		Fpage4(info.pnow,info.max_page,function(pnow){
			sessionStorage.after_record_info_pnow = pnow;
			Get_User_info();
		},60,3); //往后续查60页，每页显示3条

*/
function Get_Data_For_Fpage_Infinite_b($pdo,$pnow,$fpage_sess_name,$table_name,$primary_key,$where='',$is_desc=false,$limit=5,$ignore,$max_page,$cache_path='',$query_field,$is_return=false){
	if(is_array($where)){
		$fpage_sess_name = $fpage_sess_name.substr(md5(json_encode($where)),5,10);
	}
	if(!@$_SESSION['after_page_sess'][$fpage_sess_name]){
		if($is_desc){
			$sql = "select max({$primary_key}) as max from {$table_name}";
			$res = $pdo->dql($sql,array(),1);
			if(!$res['max']){
				exit('err5');
			}
			$_SESSION['after_page_sess'][$fpage_sess_name][$pnow] = $res['max'];
		}else{
			$_SESSION['after_page_sess'][$fpage_sess_name][$pnow] = 0;
		}
	}
	$where_primarykey2_exp = 200000; //对主键做范围限制

	if($is_desc){
		$order = "order by {$primary_key} desc";
		$diff = -1;
		$primary_key_char = '<=';
		if($_SESSION['after_page_sess'][$fpage_sess_name][$pnow] > $where_primarykey2_exp){
			$where_primarykey2 = array($primary_key,(@$_SESSION['after_page_sess'][$fpage_sess_name][$pnow]-$where_primarykey2_exp),'>');
		}
	}else{
		$order = '';
		$diff = 1;
		$primary_key_char = '>=';
		$where_primarykey2 = array($primary_key,(@$_SESSION['after_page_sess'][$fpage_sess_name][$pnow]+$where_primarykey2_exp),'<');
	}
	$where_primarykey = array($primary_key,@$_SESSION['after_page_sess'][$fpage_sess_name][$pnow],$primary_key_char);
	if(isset($where_primarykey2)){
		array_unshift($where, $where_primarykey2);
	}
	if(is_array($where)){
		array_unshift($where, $where_primarykey);
	}else{
		$where = array($where_primarykey);
	}

	$where_stat = false;
	foreach($where as $v){
		if($v[0] == $primary_key && $v[2] == '='){
			$where_stat = true;
		}
	}

	if($where_stat){
		foreach($where as $k=>$v){
			if($v[0] == $primary_key && $v[2] != '='){
				unset($where[$k]);
			}
		}
	}

	//dump($where);



	$res = Get_Data_For_Fpage_Infinite_a($pdo,$table_name,$primary_key,$where,$order,$limit,$ignore,$max_page,$query_field);
	//dump($res,1);
	if($res){
		//dump($res,1);
		$loop = floor(count($res['ids']) / $limit);
		for($i=1;$i<=$loop;$i++){
			if(isset($res['ids'][$i*$limit])){
				$_SESSION['after_page_sess'][$fpage_sess_name][$pnow+$i] = $res['ids'][$i*$limit][$primary_key];
			}
		}

		//获取最后一页的页码
		$keys = array_keys($_SESSION['after_page_sess'][$fpage_sess_name]);
		$max_page = end($keys);	
		$arr_merge = array('pnow'=>$pnow,'max_page'=>$max_page);
		if($is_return){
			return Merge_Or_Make_Cache3($res['data'],$cache_path,$arr_merge,$is_return);
		}else{
			Merge_Or_Make_Cache3($res['data'],$cache_path,$arr_merge);
		}
	}else{
		echo 'err';
	}
}













/*
	### 检测验证码是否正确
		返回：正确返回ture,失败返回false
		示例：
		if(!Verify_Code()){
			exit('e1');
		}
*/
function Verify_Code(){
	if(strtolower($_SESSION['code']) != strtolower(@$_POST['code'])){
		return false;
	}else{
		$_SESSION['code'] = md5(mt_rand());
		return true;
	}
}












/*
	### 递归创建目录
	### 参一：目录路径
*/
function Mkdirs($p){
	if(!is_dir($p)){
		Mkdirs(dirname($p),0777,true);
		mkdir($p);
	}
}



/*
	### 删除指定缓存页面中的某条数据
		参一：缓存文件名
		参二：要删除数据的id
		参三：和删除id比对的字段名
		示例：
			Del_Cache_Item('Cache/User/2',72,'info_id');
*/
function Del_Cache_Item($file_name,$id,$feild){
	if(!file_exists($file_name)){
		return;
	}
	$index = '';
	$me_infos = json_decode(file_get_contents($file_name),1);
	foreach($me_infos as $k=>$v){
		if($v[$feild] == $id){
			$index = $k;
			array_splice($me_infos,$k,1);
		}
	}
	if(count($me_infos) < 1){
		unlink($file_name);
	}else{
		file_put_contents($file_name,json_encode($me_infos));
	}
	return $index;
}




/*
	### 向指定缓存页面中添加一条数据
		参一：缓存文件名
		参二：要添加的数组格式数据
		示例：
			Add_Cache_Item('Cache/User/2',$arr);

			//user缓存数组样例
			$cache_arr['info_id'] = $info_new_id;		//向缓步文件中添加的数据
			$cache_arr['info_service'] = $_POST['info_service'];
			$cache_arr['info_title'] = $_POST['info_title'];
			$cache_arr['info_view_time'] = $_POST['info_view_time'];
			$cache_arr['info_auto_issue'] = $_POST['info_auto_issue'];
*/
function Add_Cache_Item($file_name,$arr,$index=''){
	if(!file_exists($file_name)){
		return;
	}
	$me_infos = json_decode(file_get_contents($file_name),1);
	if($index){
		$a[$index]=$arr;
		array_splice($me_infos,$index,0,$a);
	}else{
		array_unshift($me_infos, $arr);
	}
	file_put_contents($file_name, json_encode($me_infos));
}







/*
	### 修改指定缓存中的数据
		参一：缓存文件名
		参二：要修改的数据，二维索引数组 array(array(key,val),array(key,val))
		参三：比对字段下标	默认false是修改用户信息列表缓存，有值时是修改指定详情静态缓存
		参四：比对字段值	同上
		示例：
			//修改用户信息列表静态缓存
			$change_arr = array(
				array(1,$_POST['info_service']),
				array(2,$_POST['info_title']),
				array(4,$_POST['info_auto_issue'])
			);
			Cache_Modify('Cache/User/'.$_COOKIE['uid'],$change_arr,0,$_POST['info_id']);
			说明：
				比对下标0的值为info_id的那条缓存，修改其下标1,2,4的值为对应值


			//修改详情静态缓存
			$change_detail = array(
				array('3',$_POST['info_title']),
				array('4',$_POST['info_content']),
				array('5',$_POST['info_contacts']),
				array('6',$_POST['info_phone']),
				array('7',$_POST['info_imgs']),
				array('11',$_POST['info_auto_issue'])
			);
			Cache_Modify('Cache/Detail/'.$_POST['info_id'],$change_detail);

*/
function Cache_Modify($file_name,$data,$compair_index=false,$compair_val=false){
	if(!file_exists($file_name)){
		return;
	}
	$content = json_decode(file_get_contents($file_name),1);
	if($compair_index !== false && $compair_val !== false){
		foreach($content as $k=>$v){
			if($v[$compair_index] == $compair_val){
				foreach($data as $kk=>$vv){
					$content[$k][$data[$kk][0]] = $data[$kk][1];
				}
			}
		}
		file_put_contents($file_name, json_encode($content));
	}else{
		foreach($data as $vv){
			$content[$vv[0]] = $vv[1];
		}
		file_put_contents($file_name, json_encode($content));
	}
}










/*
	### 根据文件大小计算并返回upyun图片后缀
		参一：遍历$_FILES 的元素
		return：返回upyun图片分类的后缀 如： !db80
		示例：
			$img_ext = Check_File_Size($v);
*/
function Check_File_Size($v){
	if($v['size'] < 1024*10){									//小于10k
		$img_ext = '!db80';
	}else if($v['size'] >= 1024*10 && $v['size'] < 1024*50){	//10-50k
		$img_ext = '!db50';
	}else if($v['size'] >= 1024*50 && $v['size'] < 1024*100){	//50-100k
		$img_ext = '!d40';
	}else if($v['size'] >= 1024*100 && $v['size'] < 1024*200){	//100-200k
		if($v['type'] == 'image/gif' ||$v['type'] == 'image/png' ){
			$img_ext = '!db40';
		}else{
			$img_ext = '!db30';
		}
	}else if($v['size'] >= 1024*200 && $v['size'] < 1024*300){	//200-300k
		if($v['type'] == 'image/gif' ||$v['type'] == 'image/png' ){
			$img_ext = '!db30';
		}else{
			$img_ext = '!db20';
		}
	}else if($v['size'] >= 1024*300 && $v['size']){	//300-400k
		if($v['type'] == 'image/gif' ||$v['type'] == 'image/png' ){
			$img_ext = '!db20';
		}else{
			$img_ext = '!db10';
		}
	}
	return $img_ext;
}










//打印信息
function dump($data,$stat=false){
	echo '<pre>';
		var_dump($data);
	echo '</pre>';
	if($stat){
		exit;
	}
}







/*
	### 合并数据及时间页码并创建缓存
		参一：要转成json的源数据
		参二：缓存文件的存放位置
		参三：总页数
		参四：当前页
		显示并缓合并后并存转换成json的字串
*/
function Merge_Or_Make_Cache($data,$cache_path,$PageCount=0,$PageNo=0){
	$info['time'] = time()*1000;
	$info['PageCount'] = $PageCount;
	$info['PageNo'] = $PageNo;
	$info['data'] = $data;
	echo $cache = json_encode($info);
	if($cache_path != ''){
		file_put_contents($cache_path, $cache);
	}
}




/*
	### 合并数据及时间页两项
		参一：要转成json的源数据
		参二：缓存文件的存放位置
		参三：总页数
		参四：当前页
		显示并缓合并后并存转换成json的字串
*/
function Merge_Or_Make_Cache2($data,$cache_path){
	$info['time'] = time()*1000;
	$info['data'] = $data;
	echo $cache = json_encode($info);
	file_put_contents($cache_path, $cache);
}






/*
	### 合并数据,时间及其它参数并创建缓存
		参一：要转成json的源数据
		参二：缓存文件的存放位置,空为不缓存
		参三：参数的关联数组
		参四：是直显还是return 数据，默认false为直显数据
		显示并缓合并后并存转换成json的字串
*/
function Merge_Or_Make_Cache3($data,$cache_path,$arr,$is_return=false){
	$info['time'] = time()*1000;
	if(is_array($arr) && count($arr) > 0){
		foreach($arr as $k=>$v){
			$info[$k] = $v;
		}
	}
	$info['data'] = $data;
	if($cache_path != ''){
		file_put_contents($cache_path, $cache);
	}
	if($is_return){
		return json_encode($info);
	}else{
		echo $cache = json_encode($info);
	}
}









/*
	### 将数据与js格式化的时间戳合并，返回json字串 
	###	下标0 为js格式的当前时间戳
	###	下标1 为数据
*/
function MergeTimeOrDate($data){
	$time = time()*1000;
	$info[0] = $time;
	$info[1] = $data;
	return json_encode($info);
}





/*
	###  获取指定日期的年月日当天零时的时间戳
		参一：$tag 获取哪天的的标记 如：要获取昨天的'-1 day'

		示例：
			echo $a = GetDateYmd('-1 day');		//1525968000
			echo date('Y-m-d H:i:s',$a);		//2018-05-11 00:00:00

*/
function GetDateYmd($tag){
	return strtotime(date('Y-m-d',strtotime($tag,time())));
}
